import asyncio
import logging
from typing import List, AsyncIterator

from fastapi import UploadFile
from langchain.agents import create_openai_functions_agent, AgentExecutor
from langchain_core.documents import Document
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.tools import Tool

from core.llm import get_default_llm
from models.json_response import JsonData
from service.file_service import FileService
from tools.chat_tools import get_exam_tools

logger = logging.getLogger(__name__)

def create_exam_agent(tools: List[Tool]):
    system_prompt = """
    你是出题官,请根据提供的文本和知识点生成一些试题，请勿重复内容，请使用中文。

        文本内容:{text}
        知识点的格式如下:
        {{
            "main_topic": "主题",
            "subtopics": [
                {{
                    "name": "章节名称",
                    "subtopics": [
                        {{
                            "name": "知识点名称",
                            "content": "知识点内容",
                            "subtopics": ["关键点1", "关键点2"]
                        }}
                    ]
                }}
            ]
        }}
        知识点内容:{knowledge_point}

        要求：
        1. 试题需要根据文本知识点生成
        2. 
        3. 结构要清晰，内容要专业准确
        4. 输出格式为JSON,请严格遵循示例，示例：
        [
            {{
                "topic":"题目",
                "answer":"答案",
                "parse":"试题解析，答案解析"
            }}
        ]
        """

    prompt = ChatPromptTemplate.from_messages([
        ("system", system_prompt),
        ("human", "请根据上述文本和知识点生成试题"),
        MessagesPlaceholder(variable_name="agent_scratchpad")
    ])

    llm = get_default_llm()
    agent = create_openai_functions_agent(
        llm=llm,
        tools=tools,
        prompt=prompt,
    )
    agent_executor = AgentExecutor.from_agent_and_tools(
        agent=agent,
        tools=tools,
        verbose=True,
        max_iterations=3,
        handle_parsing_errors=True,
    )
    return agent_executor

async def generate_exam_response(file_service:FileService,
                               file:List[Document],
                                knowledge_point:str)->AsyncIterator[str]:
    agent = create_exam_agent(get_exam_tools())
    data = file
    text = ""
    for chunk in data:
        text += chunk.page_content
    current_chunk=""
    async for token in exam_with_agent(agent,file_service,text,knowledge_point):
        current_chunk += token
        if token in ["\n", "\r\n","。",".","，"] or len(current_chunk) > 5:
            response = JsonData.stream_data(data=current_chunk)
            yield f"data: {response.model_dump_json()}]\n\n"
            current_chunk = ""
            await asyncio.sleep(0.1)
    if current_chunk:
        response = JsonData.stream_data(data=current_chunk)
        yield f"data: {response.model_dump_json()}]\n\n"

async def exam_with_agent(agent_executor: AgentExecutor,
                             file_service:FileService,
                             text: str,
                             knowledge_point:str) -> AsyncIterator[str]:
    try:
        result = agent_executor.invoke({"text": text, "knowledge_point": knowledge_point})
        response = result.get("output", "")
        # 逐字符流式输出
        for token in response:
            yield token
            await asyncio.sleep(0.01)
    except Exception as e:
        logging.error(f"Exam agent error: {e}")
        yield "生成试题时出现错误，请稍后重试。"

